/**
 * Copyright 2022-2022 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "model_manager/general_model_manager/core/shared_mem_allocator_impl.h"

#include <fcntl.h>

#include "infra/base/assertion.h"
#include "infra/base/securestl.h"
#include "framework/infra/log/log.h"

namespace hiai {
SharedMemAllocatorImpl::SharedMemAllocatorImpl(HIAI_ModelManagerMemAllocator_AllocateFun allocateFun,
    HIAI_ModelManagerMemAllocator_FreeFun freeFun, void* config)
    : allocateFun_(allocateFun), freeFun_(freeFun), config_(config)
{
}

SharedMemAllocatorImpl::~SharedMemAllocatorImpl()
{
    allocateFun_ = nullptr;
    freeFun_ = nullptr;
    config_ = nullptr;
}

std::vector<hiai::NativeHandle> SharedMemAllocatorImpl::Allocate(size_t size)
{
    HIAI_EXPECT_NOT_NULL_R(allocateFun_, std::vector<hiai::NativeHandle>());
    HIAI_EXPECT_NOT_NULL_R(freeFun_, std::vector<hiai::NativeHandle>());

    uint32_t allocNum = 0;
    hiai::NativeHandle cHandles[NATIVE_HANDLE_MAX];
    std::vector<hiai::NativeHandle> handles;

    allocateFun_(size, cHandles, NATIVE_HANDLE_MAX, config_, &allocNum);
    if (allocNum != 0) {
        if (allocNum > NATIVE_HANDLE_MAX) {
            FMK_LOGW("Native handles size exceeds limit, allocNum = %u, max = %u.", allocNum, NATIVE_HANDLE_MAX);
            handles.assign(cHandles, cHandles + NATIVE_HANDLE_MAX);
        } else {
            handles.assign(cHandles, cHandles + allocNum);
        }
    }

    return handles;
}

void SharedMemAllocatorImpl::Free(std::vector<hiai::NativeHandle>& handles)
{
    HIAI_EXPECT_NOT_NULL_VOID(allocateFun_);
    HIAI_EXPECT_NOT_NULL_VOID(freeFun_);

    if (!handles.empty()) {
        size_t size = handles.size();
        hiai::NativeHandle cHandles[size];
        std::copy(handles.cbegin(), handles.cend(), cHandles);

        freeFun_(cHandles, size, config_);
    }
}

std::shared_ptr<ISharedMemAllocator> ISharedMemAllocator::Create(HIAI_ModelManagerMemAllocator_AllocateFun allocateFun,
    HIAI_ModelManagerMemAllocator_FreeFun freeFun, void* config)
{
    return make_shared_nothrow<SharedMemAllocatorImpl>(allocateFun, freeFun, config);
}
} // namespace hiai
